import config from "../config/config";
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
import * as THREE from "three";
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import BaseComposer from "../base/composer/BaseComposer";
import {ShaderPass} from "three/examples/jsm/postprocessing/ShaderPass";
import {UnrealBloomPass} from "three/examples/jsm/postprocessing/UnrealBloomPass"
let eventMap={}
let obj=null
export default class app{
  init(){
    this.scenes={};
    this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 5, 1000 );
    window.camera=this.camera;
    //相机
    this.renderer = new THREE.WebGLRenderer();//渲染器
    this.scene = new THREE.Scene();//场景
    this.renderer.setSize( window.innerWidth, window.innerHeight );
    this.renderer.domElement.setAttribute("id","mainMap")
    document.getElementById("app").appendChild( this.renderer.domElement );
    let canvas=document.getElementById("mainMap");
    canvas.style.position="fixed";
    canvas.style.top=0
    canvas.style.left=0
    canvas.style.zIndex=1
    this.camera.position.z = 0;
    let controls = new OrbitControls( this.camera, this.renderer.domElement );
    this.controls=controls;
    this.light = new THREE.AmbientLight( 0xffffff,2.200 );
    this.scene.add(this.light)
    window.controls=controls;
    window.camera=this.camera;
    this.renderer.domElement.addEventListener('click', this.getIntersects.bind(this));
    let self=this;
    this.composers=[];
    this.baseComposer=new BaseComposer(this.scene,this.camera,this.renderer);
    this.scenes["lightScene"]=new THREE.Scene();
    this.createLightScene();
    this.baseComposer.addPass(this.createBasePass())
    this.setupRenderTarget();
  }
  createLightScene(){
    this.lightComposer=new BaseComposer(this.scenes["lightScene"],this.camera,this.renderer)
    this.lightPass=new UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 10.5, 6.0, 0.85 );
    this.lightPass.renderToScreen=false;
    this.lightPass.renderToScreen = false;
    this.lightPass.threshold = 0;
    this.lightPass.strength = 1.5;
    this.lightPass.radius = 0;
    this.lightComposer.addPass(this.lightPass)
    this.lightComposer.getComposer().renderToScreen=false;
  }
  setupRenderTarget() {

    const params = {
      format: THREE.DepthFormat,
      type: THREE.UnsignedShortType
    };
    if ( this.target ) this.target.dispose();

    const format = parseFloat( params.format );
    const type = parseFloat( params.type );

    this.target = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
    this.target.texture.format = THREE.RGBFormat;
    this.target.texture.minFilter = THREE.NearestFilter;
    this.target.texture.magFilter = THREE.NearestFilter;
    this.target.texture.generateMipmaps = false;
    this.target.stencilBuffer = ( format === THREE.DepthStencilFormat ) ? true : false;
    this.target.depthBuffer = true;
    this.target.depthTexture = new THREE.DepthTexture();
    this.target.depthTexture.format = format;
    this.target.depthTexture.type = type;

  }
  createBasePass(){
    this.finalShaderPass=new ShaderPass(new THREE.ShaderMaterial({
      side:THREE.DoubleSide,
      uniforms: {
        uTime:{
          value:0
        },
        baseTexture:{
          value:this.baseComposer.getComposer().renderTarget2.texture
        },
        depthTexture1:{
          value:null
        },
        lightTexture:{
          value:this.lightComposer.getComposer().renderTarget2.texture
        }
      },
      vertexShader: `
        varying vec2 vUv;
        void main(){
         vUv=uv;
         gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
        }
      `
      ,
      fragmentShader:`
        varying vec2 vUv;
        uniform sampler2D baseTexture;
        uniform sampler2D lightTexture;
        uniform sampler2D depthTexture1;
        void main(){
          gl_FragColor=texture2D(baseTexture,vUv)+texture2D(lightTexture,vUv);
        }
      `,
    }),"baseTxture")
    return this.finalShaderPass
  }
  register(eventName,fun) {
    if (!eventMap[eventName]) {
      eventMap[eventName] = []
    }
    eventMap[eventName].push(fun)
  }
  trigger(eventName,...params) {
    if (eventMap[eventName]) {
      eventMap[eventName].forEach((item) => {
        try {
          let fn = eval(item);
          fn.apply(this, params);
        } catch (e) {
          console.error(e)
        }
      })
    }
  }
  getIntersects (event) {
    window.trigger("ON_CLICK_MAP",event.clientX,event.y)
    return
    event.preventDefault();
    console.log("event.clientX:" + event.clientX)
    console.log("event.clientY:" + event.clientY)

    // 声明 raycaster 和 mouse 变量
    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2();

    // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
    raycaster.setFromCamera(mouse, window.camera);

    // 获取与raycaster射线相交的数组集合，其中的元素按照距离排序，越近的越靠前
    var intersects = raycaster.intersectObjects(this.scene.children);

    //返回选中的对象数组
    console.log(intersects)
    return intersects;
  }
  run(){
    this.init();
    let list=new config().config()
    list.forEach((item)=>{
      console.log(new item().render())
    })
    this.render()
  }
  addComposer(composer){
    this.composers.push(composer)
  }
  render(){
    //this.renderer.render( this.scene, this.camera );
    this.renderer.setRenderTarget( this.target );
    this.renderer.render( this.scene, this.camera );
    this.renderer.clear();

    this.lightComposer.getComposer().render()
    this.baseComposer.getComposer().render()
    requestAnimationFrame( this.render.bind(this) );

  }
}
app.register=function (eventName,fun) {
  if (!eventMap[eventName]) {
    eventMap[eventName] = []
  }
  eventMap[eventName].push(fun)
}
app.trigger=function (eventName,...params){
  if (eventMap[eventName]) {
    eventMap[eventName].forEach((item) => {
      try{
        let fn = eval(item);
        fn.apply(this,params);
      }
      catch (e){
        console.error(e)
      }
    })
  }
}
app.forget=function (eventName){
  if (eventMap[eventName]){
    delete eventMap[eventName]
  }
}
app.singleTon=function (){
  if (obj==null){
    obj=new app()
  }
  return obj
}
